package com.tgy.exception;


import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import com.tgy.enums.ResponseStatusEnum;
import com.tgy.result.GraceJSONResult;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 统一异常拦截处理
 * 可以针对异常的类型进行捕获，然后返回json信息到前端
 */
@ControllerAdvice
public class GlobalExceptionHandler {

    /**
     *  抓捕自定义异常
     *  返回GraceJSONResult对象
     */
    @ExceptionHandler(ResultException.class)
    @ResponseBody
    public GraceJSONResult returnMyException(ResultException e) {
        return e.getGraceJSONResult();
    }

    /**
     *  抓捕自定义异常
     *  返回ResponseStatusEnum对象
     */
    @ExceptionHandler(MyCustomException.class)
    @ResponseBody
    public GraceJSONResult returnMyException(MyCustomException e) {
        e.printStackTrace();
        return GraceJSONResult.exception(e.getResponseStatusEnum());
    }

    /**
     * 抓捕 satoken 中未登录以及token无效的异常
     */
    @ExceptionHandler(NotLoginException.class)
    @ResponseBody
    public GraceJSONResult returnNotLoginException(NotLoginException e) {
        e.printStackTrace();
        return GraceJSONResult.exception(ResponseStatusEnum.SATOKEN_FAILED);
    }

    @ExceptionHandler(NotPermissionException.class)
    @ResponseBody
    public GraceJSONResult returnNotPermissionException(NotLoginException e) {
        e.printStackTrace();
        return GraceJSONResult.exception(ResponseStatusEnum.SATOKEN_NOT_PERMISSION);
    }


    /**
     * 解决使用openFeign时参数中包含BindingResult验证类时出的问题
     * 不再需要给需要验证的controller中都加上BindingResult result参数进行验证，会在这儿进行统一验证
     */
    @ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
    @ResponseBody
    public GraceJSONResult returnException(MethodArgumentNotValidException e) {
        BindingResult result = e.getBindingResult();
        Map<String, String> map = getErrors(result);
        return GraceJSONResult.errorCustom(ResponseStatusEnum.VERIFY_NULL,map);
    }

    /**
     * 获取BO中的错误信息
     * @param result
     */
    public Map<String, String> getErrors(BindingResult result) {
        Map<String, String> map = new HashMap<>();
        List<FieldError> errorList = result.getFieldErrors();
        for (FieldError error : errorList) {
            // 发送验证错误的时候所对应的某个属性
            String field = error.getField();
            // 验证的错误消息
            String msg = error.getDefaultMessage();
            map.put(field, msg);
        }
        return map;
    }


    /*@ExceptionHandler(WriterException.class)
    public void returnMyException(WriterException e, HttpServletResponse response) throws IOException {
        PrintWriter writer = response.getWriter();
        SysAuditThreadLocalHolder.putParamerter("success",false);
        ResponseStatusEnum responseStatusEnum = e.getResponseStatusEnum();
        ResultData resultData = new ResultData(responseStatusEnum.getCode(),responseStatusEnum.getMsg(),0L,null);
        JSONObject json = JSONObject.fromObject(resultData);
        writer.print(new String(json.toString().getBytes(StandardCharsets.UTF_8),StandardCharsets.ISO_8859_1));
    }


    @ExceptionHandler(WriterDataException.class)
    @ResponseBody
    public void returnMyException(WriterDataException e, HttpServletResponse response) throws IOException {
        PrintWriter writer = response.getWriter();
        SysAuditThreadLocalHolder.putParamerter("success",false);
        ResultData resultData = e.getResultData();
        JSONObject json = JSONObject.fromObject(resultData);
        writer.print(new String(json.toString().getBytes(StandardCharsets.UTF_8),StandardCharsets.ISO_8859_1));
    }*/

}
